package com.brillilab.starter.controller.aio.topics;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.common.constant.TimeConstant;
import com.brillilab.common.entity.PageVo;
import com.brillilab.common.entity.ResponseVo;
import com.brillilab.common.redis.RedisCache;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.po.system.FileManage;
import com.brillilab.domain.po.topics.Topic;
import com.brillilab.domain.po.user.Users;
import com.brillilab.domain.vo.lab.MemberInfoVo;
import com.brillilab.domain.vo.topics.TopicAddFileVo;
import com.brillilab.domain.vo.topics.TopicAddReturnVo;
import com.brillilab.domain.vo.topics.TopicAddVo;
import com.brillilab.domain.vo.topics.TopicEditVo;
import com.brillilab.domain.vo.topics.TopicExperimentFileCheckVo;
import com.brillilab.domain.vo.topics.TopicFileTypeVo;
import com.brillilab.domain.vo.topics.TopicInfoVo;
import com.brillilab.domain.vo.topics.TopicListVo;
import com.brillilab.domain.vo.topics.TopicMemberVo;
import com.brillilab.domain.vo.topics.TopicNameVo;
import com.brillilab.domain.vo.topics.TopicRecycleBinVo;
import com.brillilab.domain.vo.topics.TopicSearchVo;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.core.system.IFileManageService;
import com.brillilab.service.core.topics.ITopicMemberService;
import com.brillilab.service.core.topics.ITopicService;
import com.brillilab.service.core.user.IUsersService;
import com.brillilab.service.logic.topics.TopicLogic;
import com.brillilab.service.logic.user.UsersLogic;
import com.brillilab.service.module.message.producer.MessageProducer;
import com.brillilab.service.module.message.template.impl.topic.MainExecutorEndTopicTemp;
import com.brillilab.starter.aspect.AspectLog;
import com.brillilab.starter.constant.StarterConstant;

/**
 * 课题Controller
 * 
 * @author lj
 *
 */
@RestController
@RequestMapping("/api/topic")
public class TopicController {
	@Resource
	private UsersLogic usersLogic;
	@Autowired
	private TopicLogic topicLogic;
	@Resource
	private IFileManageService fileManageService;
	@Resource
	private IUsersService usersService;
	@Resource
	private ITopicMemberService topicMemberService;
	@Resource
	private ITopicService topicService;
	@Resource
	private MessageProducer messageProducer;
	@Resource
	private RedisCache redisCache;

	/**
	 * 课题列表成员筛选列表
	 * 
	 * @return
	 */
	@GetMapping("/screenMember")
	public ResponseVo topicMemberScreenList(@RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		Map<String, List<MemberInfoVo>> map = topicLogic.topicScreenMemberList(userInfo.getLabId(),
				userInfo.getLabMemberId(), userInfo.getIsOwner());
		return ResponseVo.success(map);
	}

	/**
	 * 课题列表
	 * 
	 * @return
	 */
	@PostMapping("/list")
	public ResponseVo topicList(@RequestBody TopicSearchVo searcVo,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		searcVo.setLabId(userInfo.getLabId());
		searcVo.setOwner(userInfo.getIsOwner());
		PageVo<TopicListVo> pageVo = topicLogic.getIndexTopicList(searcVo, userInfo);
		return ResponseVo.success(pageVo);
	}

	/**
	 * 可选课题主执行人
	 * 
	 * @return
	 */
	@GetMapping("/optionalExecutor")
	public ResponseVo optionalExecutorList(@RequestHeader(name = StarterConstant.TOKEN) String token) {
		Assert.isTrue(StringUtils.isNotBlank(token), "请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		List<MemberInfoVo> mainExecutorList = topicLogic.getOptionalExecutorList(userInfo.getLabId(),
				userInfo.getLabMemberId(), userInfo.getIsOwner());
		return ResponseVo.success(mainExecutorList);
	}

	/**
	 * 可选课题成员列表
	 * 
	 * @return
	 */
	@GetMapping("/optionalMember")
	public ResponseVo optionalMemberList(@RequestParam Long executorId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		List<MemberInfoVo> memberList = new ArrayList<MemberInfoVo>();
		if (executorId != null) {
			UserInfoVo userInfo = usersLogic.getUserByToken(token);
			memberList = topicLogic.getOptionalMemberList(executorId, userInfo.getLabId());
		}
		return ResponseVo.success(memberList);
	}

	/**
	 * 获取课题附件类型
	 * 
	 * @return
	 */
	@GetMapping("/fileType")
	public ResponseVo topicFileType() {
		List<TopicFileTypeVo> voList = new ArrayList<>();
		voList.add(new TopicFileTypeVo(OssFileEnum.TopicProjectPlanFile.getKey(), "项目计划书"));
		voList.add(new TopicFileTypeVo(OssFileEnum.TopicProjectBudgetFile.getKey(), "项目预算表"));
		voList.add(new TopicFileTypeVo(OssFileEnum.TopicResultDataFile.getKey(), "结果数据"));
		voList.add(new TopicFileTypeVo(OssFileEnum.TopicRepresentativeWorksFile.getKey(), "代表性论著"));
		voList.add(new TopicFileTypeVo(OssFileEnum.TopicPatentFile.getKey(), "专利文档"));
		voList.add(new TopicFileTypeVo(OssFileEnum.TopicOtherFile.getKey(), "其他"));
		return ResponseVo.success(voList);
	}

	/**
	 * 新建课题
	 * 
	 * @return
	 */
	@PostMapping("/add")
	public ResponseVo topicAdd(@RequestBody TopicAddVo addVo,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {

		Assert.isTrue(addVo != null && StringUtils.isNotBlank(addVo.getName()) && addVo.getExecutorId() != null,
				"请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		addVo.setLabId(userInfo.getLabId());
		// 文件名检测
		if (CollectionUtils.isNotEmpty(addVo.getTopicFileList())) {
			List<FileManage> fileManageList = new ArrayList<>();
			for (TopicAddFileVo file : addVo.getTopicFileList()) {
				fileManageList.addAll(file.getFileList());
			}
			if (CollectionUtils.isNotEmpty(fileManageList)) {
				for (FileManage file : fileManageList) {
					Assert.isTrue(!file.getName().contains("%"), "文件名包含特殊字符，请核实！");
					break;
				}
			}
		}
		TopicAddReturnVo vo = topicLogic.createNewTopic(addVo, userInfo);
		return ResponseVo.success(vo);
	}

	/**
	 * 删除课题
	 * 
	 * @return
	 */
	@GetMapping("/delete")
	public ResponseVo topicDelete(@RequestParam Long topicId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {

		Assert.isTrue(topicId != null && StringUtils.isNotBlank(token), "请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		Topic topic = topicService.selectById(topicId);
		boolean isPower = topicLogic.topicEditPower(topic, userInfo);
		Assert.isTrue(isPower, "你没有权限删除该课题");

		topicService.deleteById(topicId);
		return ResponseVo.success();
	}

	/**
	 * 结束课题
	 * 
	 * @return
	 */
	@GetMapping("/end")
	public ResponseVo topicEnd(@RequestParam Long topicId, @RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		Topic topic = topicService.selectById(topicId);
		boolean isPower = topicLogic.topicEditPower(topic, userInfo);
		Assert.isTrue(isPower, "你没有权限结束该课题");
		
		topicLogic.endTopic(topic, userInfo);

		this.mainExecutorEndTopicTemp(topic);
		return ResponseVo.success();
	}

	private void mainExecutorEndTopicTemp(Topic topic) {
		MemberInfoVo superior = topicLogic.getMemberSuperior(topic.getLabId(), topic.getExecutorId());
		if (!topic.getExecutorId().equals(superior.getLabMemberId())) {
			MainExecutorEndTopicTemp temp = new MainExecutorEndTopicTemp(topic.getLabId(), superior.getUserId(),
					superior.getLabMemberId(), topic.getName(), topic.getId());
			messageProducer.sendMessagePush(temp);
		}
	}

	/**
	 * 获取课题信息
	 *
	 * @param topicId
	 * @param token
	 * @return
	 */
	@GetMapping("/info")
	public ResponseVo getTopicInfo(@RequestParam Long topicId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		Assert.isTrue(topicId != null && StringUtils.isNotBlank(token), "请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		TopicInfoVo topicInfoVo = topicLogic.getTopicInfo(topicId, userInfo.getLabId(), userInfo.getLabMemberId());
		return ResponseVo.success(topicInfoVo);
	}

	/**
	 * 课题列表成员列表
	 * 
	 * @return
	 */
	@GetMapping("/memberList")
	public ResponseVo memberList(@RequestParam Long topicId, Integer state,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		Assert.isTrue(topicId != null && StringUtils.isNotBlank(token), "请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		List<TopicMemberVo> memberList = topicLogic.getTopicMemberList(topicId, state, userInfo.getLabId(),
				userInfo.getLabMemberId());
		return ResponseVo.success(memberList);
	}

	/**
	 * 课题编辑
	 *
	 * @return
	 */
	@AspectLog
	@PostMapping("/edit")
	public ResponseVo topicEdit(@RequestBody TopicEditVo editVo,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		Assert.isTrue(editVo != null && editVo.getId() != null && StringUtils.isNotBlank(editVo.getName()), "请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);

		// 文件名检测
		if (CollectionUtils.isNotEmpty(editVo.getTopicFileList())) {
			List<FileManage> fileManageList = new ArrayList<>();
			for (TopicAddFileVo file : editVo.getTopicFileList()) {
				fileManageList.addAll(file.getFileList());
			}
			if (CollectionUtils.isNotEmpty(fileManageList)) {
				for (FileManage file : fileManageList) {
					Assert.isTrue(!file.getName().contains("%"), "文件名包含特殊字符，请核实！");
					break;
				}
			}
		}

		TopicAddReturnVo vo = topicLogic.editTopic(editVo, userInfo);
		return ResponseVo.success(vo);
	}

	/**
	 * 判断当前用户是否可以新增课题
	 * 
	 * @param token
	 * @return
	 */
	@GetMapping("/canAdd")
	public ResponseVo canAdd(@RequestHeader(name = StarterConstant.TOKEN) String token) {
		return ResponseVo.success(true);
	}

	/**
	 * 判断当前用户是否是课题成员
	 * 
	 * @param token
	 * @return
	 */
	@GetMapping("/isMember")
	public ResponseVo isTopicMember(Long topicId, @RequestHeader(name = StarterConstant.TOKEN) String token) {
		Assert.isTrue(StringUtils.isNotBlank(token), "请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		boolean rs = topicLogic.isTopicMember(topicId, userInfo.getLabMemberId());
		return ResponseVo.success(rs);
	}

	/**
	 * 课题实验附件数据密码校验
	 *
	 * @return
	 */
	@PostMapping("/fileCheck")
	public ResponseVo fileCheck(@RequestBody TopicExperimentFileCheckVo checkVo,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		FileManage file = fileManageService.selectById(checkVo.getFileId());
		Assert.notNull(file, "文件不存在");
		Assert.isTrue(userInfo.getLabId().equals(file.getLabId()), "您没有权限查看他人实验室文件");

		Users user = usersService.selectUser(userInfo.getId(), null);
		Assert.isTrue(user.getSecurityPwd().equals(DigestUtils.md5Hex(checkVo.getDataPassword()).toUpperCase()),
				"数据密码不正确");
		redisCache.set("DataPwd:" + userInfo.getToken(), "TRUE", TimeConstant.ONE_HOUR * 3);
		return ResponseVo.success();
	}

	/**
	 * 判断附件数据密码是否已校验
	 *
	 * @return
	 */
	@GetMapping("/isFileCheck")
	public ResponseVo isFileCheck(@RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		String str = redisCache.get("DataPwd:" + userInfo.getToken());
		if (StringUtils.isNotBlank(str)) {
			return ResponseVo.successMap("isFileCheck", BoolEnum.TRUE.getValue());
		}
		return ResponseVo.successMap("isFileCheck", BoolEnum.FALSE.getValue());
	}

	/**
	 * 课题成员审核
	 * 
	 * @return
	 */
	@GetMapping("/member/audit")
	public ResponseVo topicMemberAudit(@RequestParam Long topicMemberId, @RequestParam Integer isAdopt,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		topicMemberService.topicMemberAudit(topicMemberId, isAdopt);
		return ResponseVo.success();
	}

	/**
	 * 课题回收站
	 * 
	 * @return
	 */
	@GetMapping("/recycleBin")
	public ResponseVo recycleBin(@RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		List<TopicRecycleBinVo> voList = topicLogic.recycleBinList(userInfo);
		return ResponseVo.success(voList);
	}

	/**
	 * 课题回收站-恢复课题
	 * 
	 * @return
	 */
	@AspectLog
	@GetMapping("/recovery")
	public ResponseVo recoveryTopic(@RequestParam Long topicId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		Topic topic = topicService.selectById(topicId);
		boolean isPower = topicLogic.topicEditPower(topic, userInfo);
		Assert.isTrue(isPower, "你没有权限操作该课题");

		topic.setIsDelete(BoolEnum.FALSE.getValue());
		topicService.updateById(topic);
		return ResponseVo.success();
	}

	/**
	 * 根据ID和类型获取名称
	 * 
	 * @param id
	 * @param type
	 * @return
	 */
	@AspectLog
	@GetMapping("/getName")
	public ResponseVo getName(@RequestParam Long id, @RequestParam Integer type) {
		TopicNameVo vo = topicLogic.getName(id, type);
		return ResponseVo.success(vo);
	}

}
